package com.dailyblue.java.spring.security.security03.config;

import com.dailyblue.java.spring.security.security03.filter.CheckIsLoginFilter;
import com.dailyblue.java.spring.security.security03.filter.LoginTokenFilter;
import com.dailyblue.java.spring.security.security03.handler.FailureAccessDeniedHandler;
import com.dailyblue.java.spring.security.security03.handler.NotLoginAuthentication;
import com.dailyblue.java.spring.security.security03.mapper.PowersMapper;
import com.dailyblue.java.spring.security.security03.service.UsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 方法增加权限
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UsersService usersService;
    @Resource
    private NotLoginAuthentication notLoginAuthentication;
    @Resource
    private FailureAccessDeniedHandler failureAccessDeniedHandler;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private PowersMapper powersMapper;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info("进入SecurityConfig的configure方法");
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        auth.userDetailsService(usersService).passwordEncoder(passwordEncoder);
    }

    /**
     * 配置访问过滤
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(notLoginAuthentication) // 未登录 handler
                .accessDeniedHandler(failureAccessDeniedHandler) // 无权限
                .and().csrf().disable() // 关闭 csrf 跨域请求
                .formLogin()
                .loginProcessingUrl("/user/login")  // 设定登录请求接口
                .usernameParameter("ecode")
                .passwordParameter("epass")
                .permitAll()
                .and()
                .authorizeRequests() // 请求设置
                .antMatchers("/test").permitAll() // 配置不需要认证的接口
                .anyRequest().authenticated() // 任何请求都需要认证
                .and()
                .addFilter(new LoginTokenFilter(authenticationManager(),redisTemplate)) // 认证交给 自定义 TokenLoginFilter 实现
                .addFilter(new CheckIsLoginFilter(authenticationManager(), redisTemplate,powersMapper))
                .httpBasic();
    }

    @Bean
    PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
